﻿using System;

namespace DotNetImage.Imaging.Filters
{
    /// <summary>
    /// This one works by working out the greatest difference between a central pixel and it's eight neighbours.
    /// Calculation is made per color.
    /// <remarks><para>The filter finds objects' edges by calculating maximum difference
    /// of processing pixel with neighboring pixels in 8 direction.</para>
    /// 
    /// <para>Suppose 3x3 square element of the source image (x - is currently processed pixel):
    /// <code lang="none">
    /// P1 P2 P3
    /// P8  x P4
    /// P7 P6 P5
    /// </code>
    /// The corresponding pixel of the result image equals to:
    /// <code lang="none">
    /// max( |x-P1|, |x-P2|, |x-P3|, |x-P4|,
    ///      |x-P5|, |x-P6|, |x-P7|, |x-P8| )
    /// </code>
    /// </para>  
    /// </summary>
    public class EdgeDetectHomogenityFilter : Conv3x3
    {
        [ParameterAttribute(Name = "Treshold", DefaultValue = 0, MinValue = 0, MaxValue = 255, Step = 1)]
        public byte Treshold { get; set; }

        [ParameterAttribute(Name = "Edge Detection Type", DefaultValue = (int)EdgeDetectionType.EDGE_DETECT_HOMOGENITY)]
        public EdgeDetectionType DetectionType { get { return EdgeDetectionType.EDGE_DETECT_HOMOGENITY; } }

        protected override void PrepareData(DotNetImage bmp)
        {
            base.PrepareData(bmp);
            bmp.CreatePixelCopy();
            startX = 1;
            startY = 1;
        }

        protected override void ProcessPixel(ref Pixel pix, uint x = 0, uint y = 0)
        {
            Pixel pix22 = Subject.GetPreservedPixel(x, y);
            Pixel pix11 = pix22.Clone(); pix11.SubtractAbs(Subject.GetPreservedPixel(x - 1, y - 1));
            Pixel pix12 = pix22.Clone(); pix11.SubtractAbs(Subject.GetPreservedPixel(x, y - 1));
            Pixel pix13 = pix22.Clone(); pix11.SubtractAbs(Subject.GetPreservedPixel(x + 1, y - 1));
            Pixel pix21 = pix22.Clone(); pix11.SubtractAbs(Subject.GetPreservedPixel(x - 1, y));
            Pixel pix23 = pix22.Clone(); pix11.SubtractAbs(Subject.GetPreservedPixel(x + 1, y));
            Pixel pix31 = pix22.Clone(); pix11.SubtractAbs(Subject.GetPreservedPixel(x - 1, y + 1));
            Pixel pix32 = pix22.Clone(); pix11.SubtractAbs(Subject.GetPreservedPixel(x, y + 1));
            Pixel pix33 = pix22.Clone(); pix11.SubtractAbs(Subject.GetPreservedPixel(x + 1, y + 1));

            pix = Pixel.GetMax(Treshold, pix11, pix12, pix13, pix21, pix23, pix31, pix32, pix33);
        }
    }
}
